using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using MimeCloud.AssetManagement.Business.Interface;
using MimeCloud.AssetManagement.Editor.AssetCreation.Repository;
using MimeCloud.AssetManagement.Editor.Saving;
using MimeCloud.AssetManagement.ProviderServices.Repository;
using MimeCloud.AssetManagement.ProviderServices.Data;
using MimeCloud.GDI.Imaging;
using MimeCloud.FTPUtil;

namespace MimeCloud.AssetManagement.RepositoryManagers.Web
{
    public class WebStoreHttpDownFtpUp : WebStoreRepositoryManagerBase, IRepositoryManager
    {


        #region Settings
        public String FtpDomain
        {
            get
            {
                return RepositorySettings["FtpDomain"];
            }
        }
        public String FtpUserName
        {
            get
            {
                return RepositorySettings["FtpUsername"];
            }
        }
        public String FtpPassword
        {
            get
            {
                return RepositorySettings["FtpPassword"];
            }
        }
        public String FtpPath
        {
            get
            {
                return RepositorySettings["FtpPath"].Trim(new char[] {'/', '\\'});
            }
        }
        /// <summary>
        /// If should overwrite an existing file if it doesn't exist in the database of files
        /// </summary>
        public bool OverwriteNonLinkedFile
        {
            get
            {
                return true;
            }
        }
        #endregion Settings

        /// <summary>
        /// uploads a file. assumes path has already been set
        /// </summary>
        /// <param name="assetContent"></param>
        protected override bool HardUploadContentFile(IAssetContent assetContent)
        {
            //make path ftp compatible
            assetContent.AssetPath = assetContent.AssetPath.Replace('\\', '/');
            string remoteDirPath = assetContent.AssetPath.Replace(Path.GetFileName(assetContent.AssetPath), String.Empty);
            
            //create dirs
            ensurePathExists(remoteDirPath);
            
            //assign unique ftp name by checking if file exists
            DisparateDataSaveManager.FileNameManager.AssignUniqueImageFileName(ref assetContent, assetContent2 => !QueryHelper.DoesFileExist(
                                                                                             WebPathCombine(RootPath,
                                                                                                            assetContent2
                                                                                                                .
                                                                                                                AssetPath),
                                                                                             FtpCredentials)
                                                                                             .Value);  

            //upload file
            ChangePath(WebPathCombine(RootPath,assetContent.AssetPath));
            _ff.Method = WebRequestMethods.Ftp.UploadFile;
            //_ff.UseBinary = true;

            Stream requestStream = _ff.GetRequestStream();

            Stream assetStream=null;
            //read from file if local store
            if (assetContent.AssetContentRepositoryList[0] is LocalFileStoreSingleAssetRepository)
            {
                assetStream = File.OpenRead(assetContent.AssetContentRepositoryList[0].URLPrefix);
            }
            //read from memory
            else if (assetContent.AssetContentRepositoryList[0] is MemorySingleAssetRepository)
            {
                assetStream = new MemoryStream((assetContent.AssetContentRepositoryList[0] as MemorySingleAssetRepository).AssetContent as byte[]);
            }

            //upload data
            var fileContents = new byte[assetStream.Length];
            assetStream.Read(fileContents, 0, Convert.ToInt32(assetStream.Length));
            assetStream.Close();
            _ff.ContentLength = fileContents.Length;


            requestStream.Write(fileContents, 0, fileContents.Length);

            requestStream.Close();

            var response = (FtpWebResponse)_ff.GetResponse();

            this.SaveProgressReporter(new AssetSaveProgressReport
                                          {
                                              Message =
                                                  string.Format("Upload File Complete, status {0}",
                                                                response.StatusDescription)
                                          });

            //set repository of file
            assetContent.AssetContentRepositoryList[0] = DataRepository;
            
            return true;
        }



        #region WebSpecific
        public char[] PathSeparatorCharacters
        {
            get
            {
                return new char[] { '/', Path.PathSeparator };
            }
        }

        public char PathSeparator
        {
            get
            {
                return '/';
            }
        }

        public String TrimPathChars(string source)
        {
            return source.Trim(PathSeparatorCharacters);
        }

        public string WebPathCombine(string string1, string string2)
        {
            return String.Concat(TrimPathChars(string1), PathSeparator, TrimPathChars(string2));
        }
        #endregion WebSpecific

        #region FtpSpecific
        private FtpWebRequest _ff;

        public string _rootPath;

        public string RootPath
        {
            get
            {
                if (string.IsNullOrEmpty(_rootPath))
                    _rootPath = String.Concat("ftp://", WebPathCombine(FtpDomain, FtpPath));
                return _rootPath;
            }
        }

        public ICredentials FtpCredentials
        {
            get
            {
                return new NetworkCredential(FtpUserName, FtpPassword);
            }
        }

        public void ChangePath (string path)
        {
            _ff =  QueryHelper.GetRequest(FtpCredentials, path);
        }

        public FtpStatusCode TryExecuteNonQuery()
        {
            return _ff.TryExecuteNonQuery(); 
        }



        private bool ensurePathExists(string fullPath)
        {
            return QueryHelper.EnsurePathExists(FtpCredentials, WebPathCombine(RootPath,fullPath));
        }
        #endregion FtpSpecific

    }
}
